//edited


`ifdef isALTERA
//`define USEMATH 1
`define AUDIO_FIFO 1
//`define SPI_FLASH 1

`endif
//`define JTAG t

//`define SYSTEM_VER 20210415

module system 
#(parameter H_FRONT=0, H_SYNC=0, H_BACK=0, H_DISP=0,
            V_FRONT=0, V_SYNC=0, V_BACK=0, V_DISP=0,
            SPI_QUARD=0
)
(
    input  wire        clk,  //   clk50.clk
    input  wire        reset_n,  //   reset.reset_n
    input clk_50M,
    input sdram_clk,
    input sdram_clk_trans,
    input video_clk,
 
`ifdef isSDRAM32bit
  `ifdef isDDR2
    output [1    - 1 : 0] cmd_gen_chipsel, // CFG_MEM_IF_CS_WIDTH
    output [3    - 1 : 0] cmd_gen_bank, // CFG_MEM_IF_BA_WIDTH
    output [14   - 1 : 0] cmd_gen_row, // CFG_MEM_IF_ROW_WIDTH
    output [10   - 1 : 0] cmd_gen_col, // CFG_MEM_IF_COL_WIDTH
    output do_refresh,
    output my_do_activate,
    output my_do_write,
    output my_do_read,
    output my_do_auto_precharge,
    output my_do_precharge,
    input [31:0] dio_rdata,
    input [63:0] dio_rdata64,
    output [  7: 0] afi_dm,
    output [ 63: 0] afi_wdata,
    output          afi_dqs_burst,
    output          afi_wdata_valid,
    input local_init_done,
  `else
    output        sdram_cs_n,       // SDRAM 片选信号
    output        sdram_ras_n,      // SDRAM 行地址选通脉冲
    output        sdram_cas_n,      // SDRAM 列地址选通脉冲
    output        sdram_we_n,       // SDRAM 写允许位
    output [ 1:0] sdram_ba,         // SDRAM L-Bank地址线
    output [10:0] sdram_addr,       // SDRAM 地址总线
    inout  [31:0] sdram_data,        // SDRAM 数据总线
    output [3:0]  sdram_dqm,
  `endif
`else
  output        sdram_cke,                //SDRAM 时钟有效
  output        sdram_cs0_n,               //SDRAM 片选
  output        sdram_cs1_n,               //SDRAM 片选
  output        sdram_ras_n,              //SDRAM 行有效
  output        sdram_cas_n,              //SDRAM 列有效
  output        sdram_we_n,               //SDRAM 写有效
  output [ 1:0] sdram_ba,                 //SDRAM Bank地址
  output [12:0] sdram_addr,               //SDRAM 行/列地址
  inout  [15:0] sdram_data,               //SDRAM 数据
  output [ 1:0] sdram_dqm,                //SDRAM 数据掩码
`endif

    input   [2:0]  softspi_MISO,   // softspi.MISO
    output  [2:0]  softspi_MOSI,   //        .MOSI
    output  [2:0]  softspi_SCLK,   //        .SCLK
    output  [2:0]  softspi_CS,   //        .SS_n

`ifdef CH341A
    output ch341a_ack,
    output ch341a_miso,
    input ch341a_mosi,
    input ch341a_sck,
    input ch341a_cs2,
    input ch341a_cs1,
    input ch341a_cs0,
`endif

`ifdef CY7C68013A
    output cy_rst_out,
    inout [15:0] cyData,
    input cy_IFCLK                     ,
    input cy_to_fpga_CTL0_FLAGA        ,
    input cy_to_fpga_CTL2_FLAGC        ,
    input cy_to_fpga_CTL1_FLAGB        ,
    input cy_to_fpga_A7_FLAGD          ,
    output cy_from_fpga_RDY1_SLWR       ,//output
    output cy_from_fpga_RDY0_SLRD       ,//output
    output cy_from_fpga_A2_SLOE         ,//output
    input cy_A0_INT0                   ,// in from pc
    output cy_A1_INT1                   ,// out to pc
    input cy_A3_WU2                    ,
    output cy_from_fpga_A5_FIFOADR1     ,//output
`endif

`ifdef isUSB3
  input        USB3_UART_IN,
  output       USB3_RST_OUT,
  input        USB3_PCLK,
  inout [31:0] USB3_DQ,
  output [1:0] USB3_A,
  output       USB3_SLCS_N,
  output       USB3_SLWR_N,
  output       USB3_SLOE_N,
  output       USB3_SLRD_N,
  output       USB3_PKTEND_N,
  input        USB3_FLAGA,
  input        USB3_FLAGB,
  input        USB3_FLAGC,
  input        USB3_FLAGD,
  input        USB3_CMD_CLK,
  input        USB3_CMD_DAT_U2F,
  output       USB3_CMD_DAT_F2U,
  output [31:0] addr,
  input [63:0] data64,
`endif

`ifdef ft232h
  inout  [7:0] ft_AD,
  output ft_AC6_NOE,
  input  ft_AC5_CLKOUT,
  output ft_AC4_NSIWU,
  output ft_AC3_NWR,//1
  output ft_AC2_NRD,//1
  input  ft_AC1_NTXE,//0
  input  ft_AC0_NRXF,//1
  input  ft_AC7,

  output ch341a_ack,//debug模块请求置1，cs0拉低置0
  output ch341a_miso,//data out
  input  ch341a_mosi,
  input  ch341a_sck,
  input  ch341a_cs2,//data out
  input  ch341a_cs1,//data in
  input  ch341a_cs0,//cmd in /data out
`endif

    input          myuart_rxd,     //  myuart.rxd
    output         myuart_txd,     //        .txd

    output w25q64_ncs,
    output w25q64_clk,
    inout w25q64_di_io0,
    inout w25q64_do_io1,
    inout w25q64_nwp_io2,
    inout w25q64_nhold_io3,
  
    output audio_pwm,
    inout [7:0] ch375_d,
    input ch375_int,
    output reg ch375_a0,
    output reg ch375_cs_out,
    output reg ch375_rd,
    output reg ch375_wr,

    output ds1302_clk,
    inout  ds1302_dat,
    output ds1302_rst,

    output         led_data_read,
    output         led_data_write,
    output         led_ins_read,

    input hid_dat,
    input hid_clk,
    input hid_str,

    output          video_hs,
    output          video_vs,
    output          video_de,//blank
    output   [15:0] video_rgb,


    output [31:0] debug_writedata,
    output [10:0] dotPosX,
    output [10:0] dotPosY,

    output cpu_clk_sel,
    
    output video_busy,

    input dummy
  );
  

  wire [31:0] memSize;
`ifdef isSDRAM32bit
  `ifdef isDDR2
    `ifdef USE_HALF_DDR
      localparam SDRAM_SIZE_WIDTH = 28;//256Mbyte
      assign memSize = 32'h1000_0000;
    `else
      localparam SDRAM_SIZE_WIDTH = 29;//512Mbyte
      assign memSize = 32'h2000_0000;
    `endif
  `else
    localparam SDRAM_SIZE_WIDTH = 23;//8Mbyte
    assign memSize = 32'h0080_0000;
  `endif
`else
  localparam SDRAM_SIZE_WIDTH = 26;//64Mbyte
  assign memSize = 32'h0400_0000;
`endif


  wire [31:0] flushCount;

  wire        spirom_debug_read_req  ;
  wire        spirom_debug_read_ack  ;
  wire  [7:0] spirom_debug_read_data ;
  wire        spirom_debug_write_req ;
  wire        spirom_debug_write_ack ;
  wire  [7:0] spirom_debug_write_data;
  wire        spirom_debug_cs        ;


  wire [31:0] avm_m0_address;
  wire        avm_m0_request;
  wire        avm_m0_rw;
  wire [31:0] avm_m0_writedata;
  wire [ 3:0] avm_m0_byteenable;

  wire [31:0] avm_m1_address       ;
  wire        avm_m1_read          ;
  wire [31:0] debug_vga_base_addr  ;
  wire [SDRAM_SIZE_WIDTH-11-1:0] vga_base_addr;

  reg        avm_m0_waitrequest;// = sdrambus_cs ? sdrambus_waitrequest : device_waitrequest;
  reg [31:0] avm_m0_readdata   ;// = sdrambus_cs ? sdrambus_readdata    : device_readdata;

  assign debug_writedata = debug_writedata_data;

  wire          debug_reset_n;
  wire          halt_debug;
  wire          debug_step;
  wire          halt_cpu;
  //wire   [31:0] curr_data;
  //wire   [31:0] pcResult;
  //wire   [31:0] private_offset;
  //wire   [31:0] private_offset_rear;
  wire   [31:0] pc;
  wire   [31:0] cpu_address;
  wire          irq_enable;
  wire   [31:0] performance_ins_count;
  wire   [31:0] performance_clk_count;

  wire          debug_rw_req;
  wire          debug_rw;
  wire          debug_read_ins;
  wire          debug_ins_hold_value;
  wire   [31:0] debug_address_data;
  wire   [31:0] debug_address_ins;
  wire   [31:0] debug_writedata_data;

  wire          debug_regReq;
  reg           debug_regAck;
  wire          debug_regIsWrite;
  wire    [8:0] debug_regAddr;//2k/4 = 512*32bit
  wire   [31:0] debug_regWriteData;
  reg    [31:0] debug_regData;

  wire    [7:0] pc_record_index_read;
  wire   [35:0] pc_record_data;
  wire   [31:0] pc_record_index;

  wire    [7:0] debug_stash_index_read;
  wire   [31:0] debug_stash_data;
  wire    [7:0] debug_stash_index;

  wire          halt;
  
  
  wire       virtual_ins = avm_m1_address[31];
  wire       bus_id_ins = avm_m1_address[30];
  reg        avm_m1_waitrequest;// = sdrambus_cs ? sdrambus_waitrequest : device_waitrequest;
  reg [31:0] avm_m1_readdata   ;// = sdrambus_cs ? sdrambus_readdata    : device_readdata;

  always @ (*) begin
    case(bus_id_ins)
    0 :      begin avm_m1_readdata <= sdrambus_readdata_ins ;avm_m1_waitrequest <=  sdrambus_waitrequest_ins ;end //  wire spirom_cs = deviceid==32;// 0x4000_0000   avm_m0_address[31:16] == 16'h020A;
    1 :      begin avm_m1_readdata <=   spirom_readdata_ins ;avm_m1_waitrequest <=    spirom_waitrequest_ins ;end //  wire irq_Ctrl_cs = deviceid==34;//0x4400_0000  avm_m0_address[31:16] == 16'h0202;
    endcase
  end
  
  
  wire        virtual_dat = avm_m0_address[31];
  wire        bus_id = avm_m0_address[31:30] == 2'b01;
  wire [3:0]  deviceid = avm_m0_address[28:25];//[29]略去,16个设备，不略去，32个设备
  wire [24:0] device_address = avm_m0_address[24:0];//24:0 25位设备地址,低2位为0  32Mbyte 空间

  always @ (*) begin
    case(bus_id)
    0 :      begin avm_m0_readdata <= sdrambus_readdata ;avm_m0_waitrequest <=  sdrambus_waitrequest ;end //  wire spirom_cs = deviceid==32;// 0x4000_0000   avm_m0_address[31:16] == 16'h020A;
    1 :      begin avm_m0_readdata <=   device_readdata ;avm_m0_waitrequest <=    device_waitrequest ;end //  wire irq_Ctrl_cs = deviceid==34;//0x4400_0000  avm_m0_address[31:16] == 16'h0202;
    endcase
  end

  wire        avs_m1_hold_value;
  wire [31:0] avs_m1_auto_fetch_address;
  
  reg [31:0] irq_num;
  wire irq_req = irq_num!=0;
  wire [4:0] irq_id;
  singleOut32 singleOut32_ins(
    .in(irq_num),
    .out(irq_id)
  );
  reg performance_count_on;
  reg performance_count_rst;
  reg control_by_regsram;
  reg regsram_we;
  reg [8:0] regsram_addr;
  reg [3:0] regsram_be;
  reg  [31:0] regsram_data;
  wire [31:0] regsram_q;

  mycpu mycpu_inst (
    .clk                (clk),                       //       clock.clk

    .reset_n            (reset_n), //       reset.reset_n
    .avm_m0_address     (avm_m0_address),              //          m0.address
    .avm_m0_request     (avm_m0_request),                 //            .read
    .avm_m0_rw          (avm_m0_rw),                //            .write
    .avm_m0_readdata    (avm_m0_readdata),             //            .readdata
    .avm_m0_writedata   (avm_m0_writedata),            //            .writedata
    .avm_m0_byteenable  (avm_m0_byteenable),           //            .byteenable
    .avm_m0_waitrequest (avm_m0_waitrequest),          //            .waitrequest
    .irq_req            (irq_req),                //        irq0.irq
    .irq_id             (irq_id),
    //指令，直连到sdram 配上 2*4 的缓存 还有rom需要
    .avm_m1_address     (avm_m1_address    ),     //    m0.address
    .avs_m1_auto_fetch_address (avs_m1_auto_fetch_address),
    .avs_m1_hold_value  (avs_m1_hold_value ),
    .avm_m1_read        (avm_m1_read       ),        //      .read
    .avm_m1_readdata    (avm_m1_readdata   ),    //      .readdata
    .avm_m1_waitrequest (avm_m1_waitrequest), //      .waitrequest

    .debug_reset_n      (debug_reset_n     ),
    .halt_debug         (halt_debug        ),
    .debug_step         (debug_step        ),
    .halt_cpu           (halt_cpu          ),
    //.curr_data          (curr_data         ),
    //.pcResult           (pcResult          ),
    //.private_offset     (private_offset    ),
    //.private_offset_rear(private_offset_rear),
    .pc                 (pc                ),
    .cpu_address        (cpu_address       ),
    .irq_enable         (irq_enable        ),
    //.irq_addr           (irq_addr          ),
    .performance_ins_count(performance_ins_count),
    .performance_clk_count(performance_clk_count),
    .performance_count_on (performance_count_on ),
    .performance_count_rst(performance_count_rst),

    .debug_rw_req       (debug_rw_req      ),
    .debug_rw           (debug_rw          ),
    .debug_read_ins     (debug_read_ins    ),
    .debug_ins_hold_value(debug_ins_hold_value),
    .debug_address_data (debug_address_data),
    .debug_address_ins  (debug_address_ins ),
    .debug_writedata_data(debug_writedata_data),

    .halt               (halt),

    .control_by_regsram (control_by_regsram),
    .regsram_addr       (regsram_addr      ),
    .regsram_we         (regsram_we        ),
    .regsram_be         (regsram_be        ),
    .regsram_data       (regsram_data      ),
    .regsram_q          (regsram_q         ),

    .pc_record_index_read (pc_record_index_read),
    .pc_record_data       (pc_record_data      ),
    .pc_record_index      (pc_record_index     ),
    
    .debug_stash_index_read (debug_stash_index_read),
    .debug_stash_data       (debug_stash_data      ),
    .debug_stash_index      (debug_stash_index     )

  );



  wire          read_line_req;
  wire          read_line_ack;
  wire  [1+1:0] read_line_part;
  wire  [9:0]   read_line_burst;
  wire  [SDRAM_SIZE_WIDTH-11-1:0]  read_line_addr;

  wire          read_pixel_clk;
  wire [15:0]   read_pixel_data;
  wire [31:0]   read_pixel_data32;
  wire [1+9:0]  read_pixel_addr;
  
  wire  [SDRAM_SIZE_WIDTH-11-1:0]  read_line_base_addr;
  

  wire        vga_control_by_debugger;
  wire        vga_control_by_debugger_accepted;
  wire        vga_debugger_read_line_req;
  wire  [1:0] vga_debugger_read_line_part;
  wire  [9:0] vga_debugger_read_line_burst;
  wire [SDRAM_SIZE_WIDTH-11-1:0] vga_debugger_read_line_addr;//16bit support up to 65536 * 2k = 128Mbyte
  wire  [9:0] vga_debugger_read_pixel_addr;
  wire        vga_debugger_read_pixel_clk;
  wire [31:0] debug_hid;
  wire        debug_hid_req;
  wire        debug_flg;
  wire        debug_tx_to_pc_read;
  wire [31:0] debug_rx_from_pc;
  wire        debug_rx_from_pc_valid;
  
  reg  [31:0] debug_tx_to_pc;
  reg         debug_tx_to_pc_valid;
  reg         debug_rx_from_pc_read;
  wire            debug_nocache;
    


mydebugger debugger_inst (

    .clk                (clk),                       //       clock.clk
    .clk_50M            (clk_50M),
    .reset_n            (reset_n), //       reset.reset_n

`ifdef CH341A
    //external
    .ch341a_ack         (ch341a_ack ),
    .ch341a_miso        (ch341a_miso),
    .ch341a_mosi        (ch341a_mosi),
    .ch341a_sck         (ch341a_sck ),
    .ch341a_cs2         (ch341a_cs2 ),
    .ch341a_cs1         (ch341a_cs1 ),
    .ch341a_cs0         (ch341a_cs0 ),
`endif

`ifdef CY7C68013A
    .cyData(cyData),
    .cy_rst_out(cy_rst_out),
    //.cy_SDA(cy_SDA)       ,
    .cy_IFCLK(cy_IFCLK),
    .cy_to_fpga_CTL0_FLAGA(cy_to_fpga_CTL0_FLAGA),
    //.cy_to_fpga_CTL2_FLAGC(cy_to_fpga_CTL2_FLAGC),
    .cy_to_fpga_CTL1_FLAGB(cy_to_fpga_CTL1_FLAGB),
    //.cy_to_fpga_A7_FLAGD(cy_to_fpga_A7_FLAGD),
    .cy_from_fpga_RDY1_SLWR(cy_from_fpga_RDY1_SLWR)       ,//output
    .cy_from_fpga_RDY0_SLRD(cy_from_fpga_RDY0_SLRD)       ,//output
    .cy_from_fpga_A2_SLOE(cy_from_fpga_A2_SLOE)         ,//output
    .cy_A0_INT0(cy_A0_INT0)                   ,
    .cy_A1_INT1(cy_A1_INT1)                   ,
    .cy_A3_WU2(cy_A3_WU2)                    ,
    //.cy_from_fpga_A4_FIFOADR0(cy_from_fpga_A4_FIFOADR0)     ,//output
    .cy_from_fpga_A5_FIFOADR1(cy_from_fpga_A5_FIFOADR1)     ,//output
    //.cy_from_fpga_A6_PKTEND(cy_from_fpga_A6_PKTEND)       ,//output
`endif

`ifdef isUSB3
  .USB3_UART_IN    (USB3_UART_IN    ),
  .USB3_RST_OUT    (USB3_RST_OUT    ),
  .USB3_PCLK       (USB3_PCLK       ),
  .USB3_DQ         (USB3_DQ         ),
  .USB3_A          (USB3_A          ),
  .USB3_SLCS_N     (USB3_SLCS_N     ),
  .USB3_SLWR_N     (USB3_SLWR_N     ),
  .USB3_SLOE_N     (USB3_SLOE_N     ),
  .USB3_SLRD_N     (USB3_SLRD_N     ),
  .USB3_PKTEND_N   (USB3_PKTEND_N   ),
  .USB3_FLAGA      (USB3_FLAGA      ),
  .USB3_FLAGB      (USB3_FLAGB      ),
  .USB3_FLAGC      (USB3_FLAGC      ),
  .USB3_FLAGD      (USB3_FLAGD      ),
  .USB3_CMD_CLK    (USB3_CMD_CLK    ),
  .USB3_CMD_DAT_U2F(USB3_CMD_DAT_U2F),
  .USB3_CMD_DAT_F2U(USB3_CMD_DAT_F2U),
  .addr(addr),
  .data64(data64),
`endif


`ifdef ft232h
    .ft_AD (ft_AD ),
    .ft_AC6_NOE(ft_AC6_NOE),
    .ft_AC5_CLKOUT(ft_AC5_CLKOUT),
    .ft_AC4_NSIWU(ft_AC4_NSIWU),
    .ft_AC3_NWR(ft_AC3_NWR),
    .ft_AC2_NRD(ft_AC2_NRD),
    .ft_AC1_NTXE(ft_AC1_NTXE),
    .ft_AC0_NRXF(ft_AC0_NRXF),
    .ft_AC7(ft_AC7),

    .ch341a_ack (ch341a_ack ),//debug模块请求置1，cs0拉低置0
    .ch341a_miso(ch341a_miso),//data out
    .ch341a_mosi(ch341a_mosi),
    .ch341a_sck (ch341a_sck ),
    .ch341a_cs2 (ch341a_cs2 ),//data out
    .ch341a_cs1 (ch341a_cs1 ),//data in
    .ch341a_cs0 (ch341a_cs0 ),//cmd in /data out

`endif

`ifdef JTAG
`endif

`ifdef isVIVADO
    .HP0_clk      (HP0_clk     ),
    .HP0_araddr   (HP0_araddr  ),
    .HP0_arburst  (HP0_arburst ),
    .HP0_arlen    (HP0_arlen   ),
    .HP0_arready  (HP0_arready ),
    .HP0_arvalid  (HP0_arvalid ),
    .HP0_awaddr   (HP0_awaddr  ),
    .HP0_awburst  (HP0_awburst ),
    .HP0_awlen    (HP0_awlen   ),
    .HP0_awready  (HP0_awready ),
    .HP0_awvalid  (HP0_awvalid ),
    .HP0_bready   (HP0_bready  ),
    .HP0_bvalid   (HP0_bvalid  ),
    .HP0_rdata    (HP0_rdata   ),
    .HP0_rready   (HP0_rready  ),
    .HP0_rvalid   (HP0_rvalid  ),
    .HP0_wdata    (HP0_wdata   ),
    .HP0_wlast    (HP0_wlast   ),
    .HP0_wready   (HP0_wready  ),
    .HP0_wstrb    (HP0_wstrb   ),
    .HP0_wvalid   (HP0_wvalid  ),
`endif


    //cpu
    .debug_reset_n      (debug_reset_n     ),
    .halt_debug         (halt_debug        ),
    .debug_step         (debug_step        ),
    .halt_cpu           (halt_cpu          ),
    //.curr_data          (curr_data         ),
    //.pcResult           (pcResult          ),
    //.private_offset     (private_offset    ),
    //.private_offset_rear(private_offset_rear),
    .pc                 (pc                ),
    .cpu_address        (cpu_address       ),
    .irq_enable         (irq_enable        ),
    //.irq_addr           (irq_addr          ),

    .debug_rw_req       (debug_rw_req       ),
    .debug_rw           (debug_rw           ),
    .debug_read_ins     (debug_read_ins     ),
    .debug_ins_hold_value(debug_ins_hold_value),
    .debug_address_data (debug_address_data ),
    .debug_address_ins  (debug_address_ins  ),
    .debug_writedata_data(debug_writedata_data),

    .avm_m0_address     (avm_m0_address     ),              //          m0.address
    .avm_m0_request     (avm_m0_request),                 //            .read
    .avm_m0_rw          (avm_m0_rw),                //            .write
    .avm_m0_readdata    (avm_m0_readdata    ),
    .avm_m0_waitrequest (avm_m0_waitrequest ),
    .avm_m1_read        (avm_m1_read        ),
    .avm_m1_readdata    (avm_m1_readdata    ),
    .avm_m1_waitrequest (avm_m1_waitrequest ),
    .irq_req            (irq_req            ),
    .irq_id             (irq_id             ),

    .debug_regReq       (debug_regReq),
    .debug_regAck       (debug_regAck),
    .debug_regIsWrite   (debug_regIsWrite),
    .debug_regAddr      (debug_regAddr      ),//2k/4 = 512*32bit
    .debug_regWriteData (debug_regWriteData),
    .debug_regData      (debug_regData      ),

    .pc_record_index_read (pc_record_index_read),
    .pc_record_data       (pc_record_data      ),
    .pc_record_index      (pc_record_index     ),

    .debug_stash_index_read (debug_stash_index_read),
    .debug_stash_data       (debug_stash_data      ),
    .debug_stash_index      (debug_stash_index     ),

    //spirom
    .spirom_debug_read_req     (spirom_debug_read_req  ),
    .spirom_debug_read_ack     (spirom_debug_read_ack  ),
    .spirom_debug_read_data    (spirom_debug_read_data ),
    .spirom_debug_write_req    (spirom_debug_write_req ),
    .spirom_debug_write_ack    (spirom_debug_write_ack ),
    .spirom_debug_write_data   (spirom_debug_write_data),
    .spirom_debug_cs           (spirom_debug_cs        ),

    //vga
    .vga_control_by_debugger         (vga_control_by_debugger       ),
    .vga_control_by_debugger_accepted(vga_control_by_debugger_accepted),
    .vga_debugger_read_line_req      (vga_debugger_read_line_req    ),
    .vga_debugger_read_line_ack      (read_line_ack                 ),
    .vga_debugger_read_line_part     (vga_debugger_read_line_part   ),
    .vga_debugger_read_line_burst    (vga_debugger_read_line_burst  ),
    .vga_debugger_read_line_addr     (vga_debugger_read_line_addr   ),
    .vga_debugger_read_pixel_addr    (vga_debugger_read_pixel_addr  ),
    .vga_debugger_read_pixel_clk     (vga_debugger_read_pixel_clk   ),
    .vga_debugger_read_pixel_data    (read_pixel_data               ),
    .vga_debugger_read_pixel_data32  (read_pixel_data32             ),
    

    .debug_nocache                (debug_nocache),
    .debug_hid                    (debug_hid),
    .debug_hid_req                (debug_hid_req),

    .cpu_clk_sel(cpu_clk_sel),

    //misc
    .debug_flg              (debug_flg),
    .debug_tx_to_pc         (debug_tx_to_pc       ),
    .debug_tx_to_pc_valid   (debug_tx_to_pc_valid ),
    .debug_tx_to_pc_read    (debug_tx_to_pc_read  ),
    .debug_rx_from_pc       (debug_rx_from_pc     ),
    .debug_rx_from_pc_valid (debug_rx_from_pc_valid  ),
    .debug_rx_from_pc_read  (debug_rx_from_pc_read   ),
    .debug_vga_base_addr    (debug_vga_base_addr),
    .memSize                (memSize),
    .vga_base_addr          (vga_base_addr),

  .dummy(dummy)
  );


  wire device_req = (bus_id == 1'b1) && (avm_m0_request);
  wire device_waitrequest = (device_req && !device_ack);

  reg device_ack;
  reg [31:0] device_readdata;
  //4 used
  //5 used
  //6 not used
  //7 not used
  always @ (clk) begin
    case(deviceid)
    0 :      begin device_readdata <=  spirom_readdata ;device_ack <=  spirom_device_ack_reg ;end //  wire spirom_cs = deviceid==32;// 0x4000 0000
    1 :      begin device_readdata <=   cache_readdata ;device_ack <=   cache_device_ack_reg ;end //  wire cacheCtrl_cs = deviceid==33;//0x4200_0000
    2 :      begin device_readdata <=     irq_readdata ;device_ack <=     irq_device_ack_reg ;end //  wire irq_Ctrl_cs = deviceid==34;//0x4400_0000
    3 :      begin device_readdata <= mytimer_readdata ;device_ack <= mytimer_device_ack_reg ;end //  wire mytimer_cs = deviceid==35;//0x4600_0000
    4 :      begin device_readdata <=  myuart_readdata ;device_ack <=  myuart_device_ack_reg ;end //  wire myuart_cs = deviceid==36;//0x4800_0000
    5 :      begin device_readdata <= softspi_readdata ;device_ack <= softspi_device_ack_reg ;end //  wire softspi_cs = deviceid==37;//0x4A00_0000
    6 :      begin device_readdata <=     vga_readdata ;device_ack <=     vga_device_ack_reg ;end //  wire vga_cs = deviceid==38;//0x4C00_0000
    7 :      begin device_readdata <=     hid_readdata ;device_ack <=     hid_device_ack_reg ;end //  wire hid_cs = deviceid==39;//0x4E00_0000
    8 :      begin device_readdata <= regsram_readdata ;device_ack <= regsram_device_ack_reg ;end //  //0x5000_0000 ~ 51FF_FFFF
    9 :      begin device_readdata <=   audio_readdata ;device_ack <=   audio_device_ack_reg ;end //  wire audio_cs = deviceid==41;//0x5200_0000
    10:      begin device_readdata <=  ds1302_readdata ;device_ack <=  ds1302_device_ack_reg ;end //  wire config_cs = deviceid==42;//0x5400_0000
    11:      begin device_readdata <=     fpu_readdata ;device_ack <=     fpu_device_ack_reg ;end //  wire fpu_cs = deviceid==43;//0x5600_0000
    12:      begin device_readdata <=debugger_readdata ;device_ack <=debugger_device_ack_reg ;end //  //0x5800_0000
    13:      begin device_readdata <=   ch375_readdata ;device_ack <=   ch375_device_ack_reg ;end //  //0x5A00_0000
    14:      begin device_readdata <=                0 ;device_ack <=                      1 ;end //  //0x5C00_0000
    15:      begin device_readdata <= rndmisc_readdata ;device_ack <= rndmisc_device_ack_reg ;end //  wire rndmisc_cs = deviceid==40;//0x5E00_0000
    endcase
  end

  localparam STATUS_INIT              = 2'b00;
  localparam STATUS_WAIT              = 2'b01;
  localparam STATUS_DELAY             = 2'b10;

  reg  [15:0]     page_table_pos;//26 bit ，低10bit固定 为0， 赋值时无视
  reg             refresh_ins;

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire sdrambus_cs     = bus_id     == 1'b0;//0~31 主存
  wire sdrambus_cs_ins = bus_id_ins == 1'b0;

  wire [31:0] cache_config;
  wire [31:0] sdrambus_readdata;
  wire        sdrambus_waitrequest;

  wire [31:0] sdrambus_readdata_ins;    //      .readdata
  wire        sdrambus_waitrequest_ins; //      .waitrequest

  wire        dma_ctrl_ack;

  wire [9:0]  dma_len;
  wire [SDRAM_SIZE_WIDTH-1-1:0] dma_addr;
  
  wire        dma_sram_write_enable;
  wire        dma_sram_read_enable;
  wire  [8:0] dma_sram_address;
`ifdef isSDRAM32bit
  wire [31:0] dma_sram_wdata;
  wire [31:0] dma_sram_rdata;
  wire  [3:0] dma_sram_rdata_mask;
`else
  wire [15:0] dma_sram_wdata;
  wire [15:0] dma_sram_rdata;
  wire  [1:0] dma_sram_rdata_mask;
`endif
  
  wire [SDRAM_SIZE_WIDTH-2-1:0] sdrambus_address     = avm_m0_address[SDRAM_SIZE_WIDTH-1:2];//~[0] //26bit = 64Mbyte
  wire [SDRAM_SIZE_WIDTH-2-1:0] sdrambus_address_ins = avm_m1_address[SDRAM_SIZE_WIDTH-1:2];//~[0]

  wire   sdrambus_request  = sdrambus_cs  ? avm_m0_request  : 1'b0;
  wire   sdrambus_rw       = avm_m0_rw;
  wire   sdrambus_read_ins = sdrambus_cs_ins ? avm_m1_read  : 1'b0;

  wire dma_ctrl_req;
  wire dma_ctrl_read_or_write;
    

wire read_pixel_clk_mux;
`ifdef isXC6SLX16
BUFGMUX BUFGMUX_inst (
  .O(read_pixel_clk_mux),   // 1-bit output: Clock output
  .I0(vga_debugger_read_pixel_clk), // 1-bit input: Clock input (S=0)
  .I1(read_pixel_clk), // 1-bit input: Clock input (S=1)
  .S(!vga_control_by_debugger_accepted)    // 1-bit input: Clock select
);
`endif
`ifdef isXC6SLX16QM
BUFGMUX BUFGMUX_inst (
  .O(read_pixel_clk_mux),   // 1-bit output: Clock output
  .I0(vga_debugger_read_pixel_clk), // 1-bit input: Clock input (S=0)
  .I1(read_pixel_clk), // 1-bit input: Clock input (S=1)
  .S(!vga_control_by_debugger_accepted)    // 1-bit input: Clock select
);
`endif
`ifdef isXC3S400A
  assign read_pixel_clk_mux = !vga_control_by_debugger_accepted ? read_pixel_clk  : vga_debugger_read_pixel_clk;
`endif 

`ifdef isALTERA
  assign read_pixel_clk_mux = !vga_control_by_debugger_accepted ? read_pixel_clk  : vga_debugger_read_pixel_clk;
`endif 

sdrambusvga #(
.SDRAM_SIZE_WIDTH(SDRAM_SIZE_WIDTH)
)sdrambusvga_inst(
  .clk                (clk),                       //       clock.clk
  .sdram_clk          (sdram_clk),
  .sdram_clk_trans    (sdram_clk_trans),
  .reset_n            (reset_n), //       reset.reset_n


  .virtual_dat        (virtual_dat ),
  .avs_s0_address     (sdrambus_address ),
  .avs_s0_request     (sdrambus_request ),
  .avs_s0_rw          (sdrambus_rw ),
  .avs_s0_readdata    (sdrambus_readdata ),
  .avs_s0_writedata   (avm_m0_writedata ),
  .avs_s0_waitrequest (sdrambus_waitrequest ),
  .avs_s0_byteenable  (avm_m0_byteenable ),

  .virtual_ins        (virtual_ins ),
  .avs_s1_address     (sdrambus_address_ins ),     //    s0.address//不包括低两位
  .avs_s1_auto_fetch_address (avs_m1_auto_fetch_address),
  .avs_s1_hold_value  (avs_m1_hold_value),
  .avs_s1_read        (sdrambus_read_ins    ),        //      .read
  .avs_s1_readdata    (sdrambus_readdata_ins),    //      .readdata
  .avs_s1_waitrequest (sdrambus_waitrequest_ins), //      .waitrequest
  
`ifdef isSDRAM32bit
  `ifdef isDDR2
    .cmd_gen_chipsel       (cmd_gen_chipsel      ),
    .cmd_gen_bank          (cmd_gen_bank         ),
    .cmd_gen_row           (cmd_gen_row          ),
    .cmd_gen_col           (cmd_gen_col          ),
    .do_refresh            (do_refresh           ),
    .my_do_activate        (my_do_activate       ),
    .my_do_write           (my_do_write          ),
    .my_do_read            (my_do_read           ),
    .my_do_auto_precharge  (my_do_auto_precharge ),
    .my_do_precharge       (my_do_precharge      ),
    .dio_rdata             (dio_rdata            ),
    .dio_rdata64           (dio_rdata64          ),
    .afi_dm                (afi_dm               ),
    .afi_dqs_burst         (afi_dqs_burst        ),
    .afi_wdata             (afi_wdata            ),
    .afi_wdata_valid       (afi_wdata_valid      ),
    .local_init_done       (local_init_done      ),
  `else
    .sdram_cs_n (sdram_cs_n),       // SDRAM 片选信号				output            
    .sdram_ras_n(sdram_ras_n),      // SDRAM 行地址选通脉冲       output            
    .sdram_cas_n(sdram_cas_n),      // SDRAM 列地址选通脉冲       output            
    .sdram_we_n (sdram_we_n),       // SDRAM 写允许位             output            
    .sdram_ba   (sdram_ba),         // SDRAM L-Bank地址线         output reg [ 1:0] 
    .sdram_addr (sdram_addr),       // SDRAM 地址总线             output reg [10:0] 
    .sdram_data (sdram_data),        // SDRAM 数据总线            inout  [31:0]     
    .sdram_dqm  (sdram_dqm),
  `endif
`else
  //SDRAM 芯片接口
  .sdram_cke          (sdram_cke    ),
  .sdram_cs0_n        (sdram_cs0_n   ),
  .sdram_cs1_n        (sdram_cs1_n   ),
  .sdram_ras_n        (sdram_ras_n  ),
  .sdram_cas_n        (sdram_cas_n  ),
  .sdram_we_n         (sdram_we_n   ),
  .sdram_ba           (sdram_ba     ),
  .sdram_addr         (sdram_addr   ),
  .sdram_data         (sdram_data   ),
  .sdram_dqm          (sdram_dqm    ),
`endif

  //vga
  .vga_control_by_debugger(vga_control_by_debugger_accepted),
  .readLine_req       (!vga_control_by_debugger_accepted ? read_line_req   : vga_debugger_read_line_req ),
  .readLine_ack       (read_line_ack       ),
  .read_line_part     (!vga_control_by_debugger_accepted ? read_line_part  : vga_debugger_read_line_part),
  .read_line_burst    (!vga_control_by_debugger_accepted ? read_line_burst : vga_debugger_read_line_burst),
  .read_line_addr     (!vga_control_by_debugger_accepted ? read_line_addr  : vga_debugger_read_line_addr      ),//input [9:0] read_buff_addr,

  .read_pixel_data    (read_pixel_data    ),//output [15:0] buff_readA_data,
  .read_pixel_data32  (read_pixel_data32  ),//output [15:0] buff_readA_data,
  .read_pixel_addr    (!vga_control_by_debugger_accepted ? read_pixel_addr : vga_debugger_read_pixel_addr    ),//input [9:0]   buff_readB_addr,
  .read_pixel_clk     (read_pixel_clk_mux     ),//input         buff_readB_clk,

  .dma_ctrl_req          (dma_ctrl_req          ),
  .dma_ctrl_ack          (dma_ctrl_ack          ),
  .dma_ctrl_read_or_write(dma_ctrl_read_or_write),

  .dma_len               (dma_len               ),//max512
  .dma_addr              (dma_addr              ),
  .dma_sram_address      (dma_sram_address      ),
  .dma_sram_write_enable (dma_sram_write_enable ),
  .dma_sram_read_enable  (dma_sram_read_enable  ),
  .dma_sram_wdata        (dma_sram_wdata        ),
  .dma_sram_rdata        (dma_sram_rdata        ),
  .dma_sram_rdata_mask   (dma_sram_rdata_mask),

  .page_table_pos (page_table_pos),
  .refresh_ins    (refresh_ins),

  .debug_nocache         (debug_nocache),
  .flushCount            (flushCount),
  .cache_config          (cache_config),

  .led_data_read         (led_data_read),
  .led_data_write        (led_data_write),
  .led_ins_read          (led_ins_read)

);
//`endif

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire spirom_device_ack;
  wire spirom_cs  = deviceid == 0;// 0x4000_0000
  reg       spirom_device_ack_reg;
  reg [1:0] spirom_status;
  reg       spirom_device_req;
  reg       spirom_device_ack_buff;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      spirom_device_ack_reg <= 0;
      spirom_status <= 0;
      spirom_device_req <= 0;
      spirom_device_ack_buff <= 0;
    end else begin
      spirom_device_ack_buff <= spirom_device_ack;
      spirom_device_ack_reg <= 0;
      case(spirom_status)
      STATUS_INIT: begin
        if(spirom_cs)begin
          if(device_req && !spirom_device_ack_reg)begin
            spirom_device_req <= 1;
            spirom_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(spirom_device_ack_buff)begin
          spirom_device_req <= 0;
          spirom_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!spirom_device_ack_buff)begin
          spirom_device_ack_reg <= 1;
          spirom_status <= STATUS_INIT;
        end
      end
      endcase
    end
  end

  
  wire spirom_cs_ins  = bus_id_ins == 1'b1;//0x4000_0000 1G~2G 
  reg       spirom_read_ack;
  reg [1:0] spirom_status_ins;
  reg       spirom_req_ins;
  reg       spirom_ack_ins_buff;
  
  wire spirom_waitrequest_ins = (avm_m1_read && !spirom_read_ack);
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      spirom_read_ack <= 0;
      spirom_status_ins <= 0;
      spirom_req_ins <= 0;
      spirom_ack_ins_buff <= 0;
    end else begin
      spirom_ack_ins_buff <= spirom_ack_ins;
      spirom_read_ack <= 0;
      case(spirom_status_ins)
      STATUS_INIT: begin
        if(spirom_cs_ins)begin
          if(avm_m1_read && !spirom_read_ack)begin
            spirom_req_ins <= 1;
            spirom_status_ins <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(spirom_ack_ins_buff)begin
          spirom_req_ins <= 0;
          spirom_status_ins <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!spirom_ack_ins_buff)begin
          spirom_read_ack <= 1;
          spirom_status_ins <= STATUS_INIT;
        end
      end
      endcase

    end
  end
  
  wire [31:0] spirom_readdata;
  wire [31:0] spirom_readdata_ins;
  wire [22:0] spirom_address     = device_address[24:2];
  wire [22:0] spirom_address_ins = avm_m1_address[24:2];

  wire spirom_ack_ins;
`ifdef isISE

  spi spirom_inst (
    .clk_50M            (clk_50M),
    .reset_n            (reset_n), //       reset.reset_n
    .avs_s0_address     (spirom_address ),
    .avs_s0_writedata   (avm_m0_writedata ),
    .avs_s0_readdata    (spirom_readdata ),
    .device_req         (spirom_device_req ),
    .device_ack         (spirom_device_ack ),
    .avs_s0_byteenable  (avm_m0_byteenable ),

    //50M
    .avs_s1_address     (spirom_address_ins ),     //    s0.address//不包括低两位
    .avs_s1_readdata    (spirom_readdata_ins),    //      .readdata
    .avs_s1_req         (spirom_req_ins), //      .waitrequest
    .avs_s1_ack         (spirom_ack_ins), //      .waitrequest

    .debug_read_req     (spirom_debug_read_req  ),
    .debug_read_ack     (spirom_debug_read_ack  ),
    .debug_read_data    (spirom_debug_read_data ),
    .debug_write_req    (spirom_debug_write_req ),
    .debug_write_ack    (spirom_debug_write_ack ),
    .debug_write_data   (spirom_debug_write_data),
    .debug_cs           (spirom_debug_cs        ),

    .spi_ncs            (w25q64_ncs),
    .spi_clk            (w25q64_clk),
    .spi_mosi           (w25q64_di_io0),
    .spi_miso           (w25q64_do_io1)
  );
  assign w25q64_nwp_io2 = 1'b1;
  assign w25q64_nhold_io3 = 1'b1;

`else
 `ifdef SPI_QUARD
   spiquad spirom_inst ( 
 `else
   spi spirom_inst ( 
 `endif
     .clk_50M            (clk_50M),
     .reset_n            (reset_n), //       reset.reset_n
     .avs_s0_address     (spirom_address ),
     .avs_s0_writedata   (avm_m0_writedata ),
     .avs_s0_readdata    (spirom_readdata ),
     .device_req         (spirom_device_req ),
     .device_ack         (spirom_device_ack ),
     .avs_s0_byteenable  (avm_m0_byteenable ),
 
     //50M
     .avs_s1_address     (spirom_address_ins ),     //    s0.address//不包括低两位
     .avs_s1_readdata    (spirom_readdata_ins),    //      .readdata
     .avs_s1_req         (spirom_req_ins), //      .waitrequest
     .avs_s1_ack         (spirom_ack_ins), //      .waitrequest
 
     .debug_read_req     (spirom_debug_read_req  ),
     .debug_read_ack     (spirom_debug_read_ack  ),
     .debug_read_data    (spirom_debug_read_data ),
     .debug_write_req    (spirom_debug_write_req ),
     .debug_write_ack    (spirom_debug_write_ack ),
     .debug_write_data   (spirom_debug_write_data),
     .debug_cs           (spirom_debug_cs        ),
     
`ifdef SPI_QUAD
     .spi_ncs            (w25q64_ncs),
     .spi_clk            (w25q64_clk),
     .spi_mosi_io0       (w25q64_di_io0),
     .spi_miso_io1       (w25q64_do_io1),
     .spi_nwp_io2        (w25q64_nwp_io2),
     .spi_nhold_io3      (w25q64_nhold_io3)
`else
     .spi_ncs            (w25q64_ncs),
     .spi_clk            (w25q64_clk),
     .spi_mosi           (w25q64_di_io0),
     .spi_miso           (w25q64_do_io1)
`endif

   );
`endif
`ifdef SPI_QUAD
`else
  assign w25q64_nwp_io2 = 1'b1;
  assign w25q64_nhold_io3 = 1'b1;
`endif
  
  
  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire cache_cs   = deviceid == 1;//0x4200_0000

  //page_table所在内存位置
  reg [31:0] cache_readdata;// = device_address[2] == 0 ? flushCount : cache_config; //  0/4
  always @(*) begin
    case(device_address[3:2])
      0:begin cache_readdata <= memSize; end //0 // memory size // 8Mbyte
      1:begin cache_readdata <= cache_config; end //4
      2:begin cache_readdata <= flushCount; end //8
      3:begin cache_readdata <= 0; end //C
    endcase
  end

  reg cache_device_ack_reg;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      cache_device_ack_reg <= 0;
      refresh_ins <= 0;
      page_table_pos <= 0;
    end else begin
      cache_device_ack_reg <= 0;
      if(cache_cs)begin
        if(device_req && !cache_device_ack_reg)begin
          cache_device_ack_reg <= 1;
        end
        if(device_req)begin
          if(avm_m0_rw)begin
          
            if(device_address[3:2]==1)begin//4
              refresh_ins <= avm_m0_writedata[0];
            end
            
            if(device_address[3:2]==3)begin//c
              page_table_pos <= avm_m0_writedata[SDRAM_SIZE_WIDTH-1:10];//byte9:0 丢弃
            end
            
          end
        end
      end
    end
  end
  

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire irq_cs     = deviceid == 2;//0x4400_0000  avm_m0_address[31:16] == 16'h0202;
  reg       irq_device_ack_reg;
  reg [1:0] irq_status;
  reg       irq_device_req;
  reg       irq_device_ack_buff;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      irq_device_ack_reg <= 0;
      irq_status <= 0;
      irq_device_req <= 0;
      irq_device_ack_buff <= 0;
    end else begin
      irq_device_ack_buff <= irq_device_ack;
      irq_device_ack_reg <= 0;
      case(irq_status)
      STATUS_INIT: begin
        if(irq_cs)begin
          if(device_req && !irq_device_ack_reg)begin
            irq_device_req <= 1;
            irq_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(irq_device_ack_buff)begin
          irq_device_req <= 0;
          irq_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!irq_device_ack_buff)begin
          irq_device_ack_reg <= 1;
          irq_status <= STATUS_INIT;
        end
      end
      endcase
    end
  end


  
  wire [31:0] irq_readdata = irq_num;

  wire mytimer_irq_req;
  reg  mytimer_irq_ack;
  wire myuart_irq_req;
  reg  myuart_irq_ack;
  reg  hid_irq_req;
  reg  hid_irq_ack;
  reg  audio_irq_req;
  reg  audio_irq_ack;
  wire video_irq_req;
  reg  video_irq_ack;

  reg irq_device_req_buff;
  reg irq_device_ack;
  always@(posedge clk_50M or negedge reset_n) begin
    if(!reset_n) begin
      irq_num <= 0;
      mytimer_irq_ack <= 0;
      myuart_irq_ack <= 0;
      hid_irq_ack <= 0;
      audio_irq_ack <= 0;
      irq_device_req_buff <= 0;
    end else begin
    
      irq_device_req_buff <= irq_device_req;
      
      if(irq_device_req_buff && !irq_device_ack)begin
        irq_device_ack <= 1;
      end
      if(irq_device_req_buff && avm_m0_rw)begin
        irq_num <= irq_num & (~avm_m0_writedata);
      end

      if(!irq_device_req_buff && irq_device_ack)begin
        irq_device_ack <= 0;
      end

      /////////////////////////////////////////////////////////////

      if(mytimer_irq_req && !mytimer_irq_ack)begin
        irq_num[0] <= 1;
        mytimer_irq_ack <= 1;
      end
      if(!mytimer_irq_req && mytimer_irq_ack)begin
        mytimer_irq_ack <= 0;
      end

      if(myuart_irq_req && !myuart_irq_ack)begin
        irq_num[1] <= 1;
        myuart_irq_ack <= 1;
      end
      if(!myuart_irq_req && myuart_irq_ack)begin
        myuart_irq_ack <= 0;
      end
      
      if(hid_irq_req && !hid_irq_ack)begin
        irq_num[2] <= 1;
        hid_irq_ack <= 1;
      end
      if(!hid_irq_req && hid_irq_ack)begin
        hid_irq_ack <= 0;
      end
      
      if(audio_irq_req && !audio_irq_ack)begin
        irq_num[3] <= 1;
        audio_irq_ack <= 1;
      end
      if(!audio_irq_req && audio_irq_ack)begin
        audio_irq_ack <= 0;
      end

      if(video_irq_req && !video_irq_ack)begin
        irq_num[4] <= 1;
        video_irq_ack <= 1;
      end
      if(!video_irq_req && video_irq_ack)begin
        video_irq_ack <= 0;
      end

    end
  end

  
  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire mytimer_cs = deviceid == 3;//0x4600_0000 avm_m0_address[31:16] == 16'h0203;
  reg       mytimer_device_ack_reg;
  reg [1:0] mytimer_status;
  reg       mytimer_device_req;
  reg       mytimer_device_ack_buff;
  wire mytimer_device_ack;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      mytimer_device_ack_reg <= 0;
      mytimer_status <= 0;
      mytimer_device_req <= 0;
      mytimer_device_ack_buff <= 0;
    end else begin
      mytimer_device_ack_buff <= mytimer_device_ack;
      mytimer_device_ack_reg <= 0;
      case(mytimer_status)
      STATUS_INIT: begin
        if(mytimer_cs)begin
          if(device_req && !mytimer_device_ack_reg)begin
            mytimer_device_req <= 1;
            mytimer_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(mytimer_device_ack_buff)begin
          mytimer_device_req <= 0;
          mytimer_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!mytimer_device_ack_buff)begin
          mytimer_device_ack_reg <= 1;
          mytimer_status <= STATUS_INIT;
        end
      end
      endcase
    end
  end
  
  wire [4:0] mytimer_address = device_address[6:2];//~[0]

  wire [31:0] mytimer_readdata;
mytimer mytimer_inst (
  .clk_50M            (clk_50M),
  .reset_n            (reset_n), //       reset.reset_n
  .avs_s0_address     (mytimer_address ),
  .avs_s0_rw          (avm_m0_rw ),
  .avs_s0_readdata    (mytimer_readdata ),
  .avs_s0_writedata   (avm_m0_writedata ),
  .device_req         (mytimer_device_req ),
  .device_ack         (mytimer_device_ack ),
  .avs_s0_byteenable  (avm_m0_byteenable ),
  .irq_req            (mytimer_irq_req),       //  irq0.irq
  .irq_ack            (mytimer_irq_ack)
);


  
  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire myuart_cs  = deviceid == 4;//0x4800_0000 avm_m0_address[31:16] == 16'h0204;
  reg       myuart_device_ack_reg;
  reg [1:0] myuart_status;
  reg       myuart_device_req;
  reg       myuart_device_ack_buff;
  wire      myuart_device_ack;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      myuart_device_ack_reg <= 0;
      myuart_status <= 0;
      myuart_device_req <= 0;
      myuart_device_ack_buff <= 0;
    end else begin
      myuart_device_ack_buff <= myuart_device_ack;
      myuart_device_ack_reg <= 0;
      case(myuart_status)
      STATUS_INIT: begin
        if(myuart_cs)begin
          if(device_req && !myuart_device_ack_reg)begin
            myuart_device_req <= 1;
            myuart_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(myuart_device_ack_buff)begin
          myuart_device_req <= 0;
          myuart_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!myuart_device_ack_buff)begin
          myuart_device_ack_reg <= 1;
          myuart_status <= STATUS_INIT;
        end
      end
      endcase
    end
  end

  wire [31:0] myuart_readdata;
  wire        myuart_address = device_address[2];//~[0]
  //wire        myuart_waitrequest;
  myuart myuart_inst (
    .clk_50M            (clk_50M),
    .reset_n            (reset_n), //       reset.reset_n
    .avs_s0_address     (myuart_address ),
    .avs_s0_rw          (avm_m0_rw ),
    .avs_s0_readdata    (myuart_readdata ),
    .avs_s0_writedata   (avm_m0_writedata ),
    .device_req         (myuart_device_req ),
    .device_ack         (myuart_device_ack ),
    .avs_s0_byteenable  (avm_m0_byteenable ),
    .irq_req            (myuart_irq_req),       //  irq0.irq
    .irq_ack            (myuart_irq_ack),

    .uart_rxd           (myuart_rxd),
    .uart_txd           (myuart_txd)
  );
  
  
  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire softspi_cs = deviceid == 5;//0x4A00_0000 avm_m0_address[31:16] == 16'h0205;
  reg       softspi_device_ack_reg;
  reg [1:0] softspi_status;
  reg       softspi_device_req;
  reg       softspi_device_ack_buff;
  wire      softspi_device_ack;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      softspi_device_ack_reg <= 0;
      softspi_status <= 0;
      softspi_device_req <= 0;
      softspi_device_ack_buff <= 0;
    end else begin
      softspi_device_ack_buff <= softspi_device_ack;
      softspi_device_ack_reg <= 0;
      case(softspi_status)
      STATUS_INIT: begin
        if(softspi_cs)begin
          if(device_req && !softspi_device_ack_reg)begin
            softspi_device_req <= 1;
            softspi_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(softspi_device_ack_buff)begin
          softspi_device_req <= 0;
          softspi_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!softspi_device_ack_buff)begin
          softspi_device_ack_reg <= 1;
          softspi_status <= STATUS_INIT;
        end
      end
      endcase

    end
  end

  
  wire [31:0] softspi_readdata;
  wire [13:0] softspi_address = device_address[15:2];//~[0]
`ifdef isISE
//TODO
`else
sdcard sdcard_inst (
  .clk_50M            (clk_50M),
  .reset_n            (reset_n), //       reset.reset_n
  .avs_s0_address     (softspi_address ),
  .avs_s0_rw          (avm_m0_rw ),
  .avs_s0_readdata    (softspi_readdata ),
  .avs_s0_writedata   (avm_m0_writedata ),
  .device_req         (softspi_device_req ),
  .device_ack         (softspi_device_ack ),
  .avs_s0_byteenable  (avm_m0_byteenable ),
  
  .MISO           (softspi_MISO),
  .MOSI           (softspi_MOSI),
  .SCLK           (softspi_SCLK),
  .CS             (softspi_CS)
);
`endif
  
  
  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire vga_cs     = deviceid == 6;//0x4C00_0000 avm_m0_address[31:16] == 16'h0206;
  wire vga_device_ack_reg;
  wire vga_device_req = device_req && vga_cs;

  wire [31:0] vga_readdata;

  wire [24:0] video_address = device_address;//~[0]


video
#(
  .H_FRONT(H_FRONT), //行同步
  .H_SYNC(H_SYNC), //行同步
  .H_BACK(H_BACK), //行显示后沿
  .H_DISP(H_DISP),//行有效数据
  .V_FRONT(V_FRONT),  //场显示后沿
  .V_SYNC(V_SYNC),  //场同步
  .V_BACK(V_BACK),  //场显示后沿
  .V_DISP(V_DISP),  //场有效数据
  .SDRAM_SIZE_WIDTH(SDRAM_SIZE_WIDTH)
)
video_inst (
  .clk                (clk),
  .reset_n            (reset_n), //       reset.reset_n
  .video_clk          (video_clk),

  .avs_s0_address     (video_address ),
  .avs_s0_rw          (avm_m0_rw ),
  .avs_s0_readdata    (vga_readdata ),
  .avs_s0_writedata   (avm_m0_writedata ),
  .device_req         (vga_device_req ),
  .vga_device_ack     (vga_device_ack_reg ),
  .avs_s0_byteenable  (avm_m0_byteenable ),

  .vga_base_addr      (vga_base_addr),

  .sdram_clk          (sdram_clk),
  .sdram_clk_trans    (sdram_clk_trans),
  .dma_ctrl_req       (dma_ctrl_req          ),
  .dma_ctrl_ack       (dma_ctrl_ack          ),
  .dma_ctrl_read_or_write(dma_ctrl_read_or_write),
  .dma_len            (dma_len           ),
  .dma_addr           (dma_addr          ),
  .dma_sram_rdata     (dma_sram_rdata    ),
  .dma_sram_rdata_mask(dma_sram_rdata_mask),
  .dma_sram_address   (dma_sram_address  ),
  .dma_sram_wdata     (dma_sram_wdata    ),
  .dma_sram_write_enable(dma_sram_write_enable),
  .dma_sram_read_enable (dma_sram_read_enable),


  .vga_control_by_debugger(vga_control_by_debugger),
  .vga_control_by_debugger_accepted(vga_control_by_debugger_accepted),
  .read_line_req (read_line_req ),
  .read_line_ack (read_line_ack ),
  .read_line_part(read_line_part),
  .read_line_burst(read_line_burst),
  .read_line_addr(read_line_addr),

  .read_pixel_clk(read_pixel_clk),
  .read_pixel_data(read_pixel_data),
  .read_pixel_addr(read_pixel_addr),
  
  .read_line_base_addr(read_line_base_addr),
  .dotPosX(dotPosX),
  .dotPosY(dotPosY),

  .video_hs(video_hs),
  .video_vs(video_vs),
  .video_de(video_de),//blank
  .video_rgb(video_rgb),

  .video_irq_req(video_irq_req),
  .video_irq_ack(video_irq_ack),

  .video_busy(video_busy),
  .dummy(dummy)
);

  assign read_line_base_addr = debug_vga_base_addr[31] ? debug_vga_base_addr[SDRAM_SIZE_WIDTH-11-1:0] : vga_base_addr;

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire hid_cs     = deviceid == 7;//0x4E00_0000 avm_m0_address[31:16] == 16'h0207;
  reg       hid_device_ack_reg;
  reg [1:0] hid_status;
  reg       hid_device_req;
  reg       hid_device_ack_buff;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      hid_device_ack_reg <= 0;
      hid_status <= 0;
      hid_device_req <= 0;
      hid_device_ack_buff <= 0;
    end else begin
      hid_device_ack_buff <= hid_device_ack;
      hid_device_ack_reg <= 0;
      case(hid_status)
      STATUS_INIT: begin
        if(hid_cs)begin
          if(device_req && !hid_device_ack_reg)begin
            hid_device_req <= 1;
            hid_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(hid_device_ack_buff)begin
          hid_device_req <= 0;
          hid_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!hid_device_ack_buff)begin
          hid_device_ack_reg <= 1;
          hid_status <= STATUS_INIT;
        end
      end
      endcase
    end
  end

  
  reg hid_str_buff1;
  reg hid_str_buff2;
  
  reg debug_hid_req_buff1;
  reg debug_hid_req_buff2;

  reg hid_irq_ack_buff;
  reg hid_device_req_buff;
  reg hid_device_ack;
  reg [31:0] hid_readdata;
  always@(posedge clk_50M or negedge reset_n) begin
    if(!reset_n) begin
      hid_irq_req <= 0;
      hid_str_buff1 <= 0;
      hid_str_buff2 <= 0;
      debug_hid_req_buff1 <= 0;
      debug_hid_req_buff2 <= 0;
      hid_device_req_buff <= 0;
      hid_readdata <= 0;
    end else begin
      hid_str_buff1 <= hid_str;
      hid_str_buff2 <= hid_str_buff1;
      
      debug_hid_req_buff1 <= debug_hid_req;
      debug_hid_req_buff2 <= debug_hid_req_buff1;

      hid_device_req_buff <= hid_device_req;
      
      if(hid_device_req_buff && !hid_device_ack)begin
        hid_device_ack <= 1;
        if(avm_m0_rw) begin
          hid_readdata <= 0;
        end
      end

      if(!hid_device_req_buff && hid_device_ack)begin
        hid_device_ack <= 0;
      end

      hid_irq_ack_buff <= hid_irq_ack;
      
      // new              old
      if(hid_str_buff1 && !hid_str_buff2)begin//上升沿
        hid_readdata <= {1'b1,hid_data[30:0]};
        hid_irq_req <= 1;
      end
      
      // new              old
      if(debug_hid_req_buff1 && !debug_hid_req_buff2)begin//上升沿
        hid_readdata <= {1'b1,debug_hid[30:0]};
        hid_irq_req <= 1;
      end


      if(hid_irq_ack_buff)begin
        hid_irq_req <= 0;
      end
    end
  end
  

  reg [31:0] hid_data;
  always@(posedge hid_clk or negedge reset_n) begin
    if(!reset_n) begin
      hid_data <= 0;
    end else begin
      hid_data <= {hid_dat,hid_data[31:1]};
    end
  end
  

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire regsram_cs  = deviceid == 8;// 0x5000_0000

  // wire          debug_regReq;
  // reg           debug_regAck;
  // wire          debug_regIsWrite;
  // wire    [8:0] debug_regAddr;//2k/4 = 512*32bit
  // wire   [31:0] debug_regWriteData;
  // reg    [31:0] debug_regData;

  reg [32:0] regsram_q_latch;
  reg debug_regReq_buff;
  reg       regsram_device_ack_reg;
  reg [2:0] regsram_status;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      regsram_device_ack_reg <= 0;
      regsram_status <= 0;
      control_by_regsram <= 0;
      regsram_we <= 0;
      regsram_q_latch <= 0;
      debug_regReq_buff <= 0;
      debug_regAck <= 0;
      regsram_data <= 0;
      regsram_addr <= 0;
      regsram_be <= 0;
    end else begin
      regsram_device_ack_reg <= 0;
      debug_regReq_buff <= debug_regReq;
      regsram_we <= 0;
      case(regsram_status)
      0: begin
        control_by_regsram <= 0;
        if(regsram_cs)begin
          if(device_req && !regsram_device_ack_reg)begin
            control_by_regsram <= 1;
            regsram_data <= avm_m0_writedata;
            regsram_we <= avm_m0_rw;
            regsram_addr <= device_address[10:2];
            regsram_be <= avm_m0_byteenable;
            regsram_status <= 1;
          end
        end
        if(debug_regReq_buff)begin
          control_by_regsram <= 1;
          regsram_data <= debug_regWriteData;
          regsram_we <= debug_regIsWrite;
          regsram_addr <= debug_regAddr;
          regsram_be <= 4'b1111;
          regsram_status <= 3;
        end
      end
      1: begin
        regsram_status <= 2;
      end
      2: begin
        control_by_regsram <= 0;
        regsram_q_latch <= regsram_q;
        regsram_device_ack_reg <= 1;
        regsram_status <= 0;
      end
      3: begin
        regsram_status <= 4;
      end
      4: begin
        control_by_regsram <= 0;
        debug_regData <= regsram_q;
        debug_regAck <= 1;
        regsram_status <= 0;
      end

      endcase
      if(debug_regAck && !debug_regReq_buff)begin
        debug_regAck <= 0;
      end
    end
  end
  
  wire [31:0] regsram_readdata = regsram_q_latch;


  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire audio_cs  = deviceid == 9;//0x5200_0000 avm_m0_address[31:16] == 16'h0209;
  reg       audio_device_ack_reg;
  reg [1:0] audio_status;
  reg       audio_device_req;
  reg       audio_device_ack_buff;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      audio_device_ack_reg <= 0;
      audio_status <= 0;
      audio_device_req <= 0;
      audio_device_ack_buff <= 0;
    end else begin
`ifdef isALTERA
      audio_device_ack_buff <= audio_device_ack;
      audio_device_ack_reg <= 0;
      case(audio_status)
      STATUS_INIT: begin
        if(audio_cs)begin
          if(device_req && !audio_device_ack_reg)begin
            audio_device_req <= 1;
            audio_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(audio_device_ack_buff)begin
          audio_device_req <= 0;
          audio_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!audio_device_ack_buff)begin
          audio_device_ack_reg <= 1;
          audio_status <= STATUS_INIT;
        end
      end
      endcase
`endif
    end
  end
  
  
  assign audio_pwm = audio_pwm_reg;
  
  //50,000,000 / 1134 = 44091.71   //567
  reg audio_pwm_reg;
  reg [3:0] clk_audio;// 44.1khz
  reg [8:0] clk_audio_count;//283 = 1134/4
  reg audio_ena;
  reg audio_wrreq;
  reg [31:0] audio_readdata;
  reg audio_device_ack;
  reg audio_device_req_buff;
  reg audio_wrusedw_old;
  always@(posedge clk_50M or negedge reset_n) begin
    if(!reset_n) begin
      clk_audio_count <= 0;
      clk_audio <= 0;
      audio_pwm_reg <= 0;
      audio_readdata <= 0;
      audio_ena <= 0;
      audio_wrreq <= 0;
      audio_device_ack <= 0;
      audio_device_req_buff <= 0;
      audio_wrusedw_old <= 0;
    end else begin
`ifdef isALTERA

      audio_device_req_buff <= audio_device_req;
    
      audio_wrreq <= 0;
    
      if(audio_device_req_buff && !audio_device_ack)begin
        audio_device_ack <= 1;
        if(avm_m0_rw)begin
        
          if(device_address[2]==0)begin
            audio_wrreq <= 1;
          end else begin
            audio_ena <= avm_m0_writedata[0];
          end
          
        end else begin
          audio_readdata <= audio_wrusedw;
        end

      end

      if(!audio_device_req_buff && audio_device_ack)begin
        audio_device_ack <= 0;
      end

    
    
      clk_audio_count <= clk_audio_count + 1'b1;
      
      if(clk_audio_count[8]==0)begin
        if(clk_audio_count[7:0]<=audio_data_out)begin//前半1，后半0
          audio_pwm_reg <= 1;
        end else begin
          audio_pwm_reg <= 0;
        end
      end else begin
        if(clk_audio_count[7:0]>13)begin//283-256=27,13
          audio_pwm_reg <= 1;
        end else begin
          audio_pwm_reg <= 0;
        end
      end
      
      if(!audio_ena)begin
        audio_pwm_reg <= 0;
      end
      
      if(clk_audio_count==283)begin
        clk_audio_count <= 0;
        
        clk_audio <= clk_audio+1'b1;
        //if(clk_audio==0)begin
        //  audio_rdaddress = audio_rdaddress+ 1'b1;
        //end
      end
      
      if(audio_rdempty)begin
        audio_ena <= 0;
      end
      
      
      audio_wrusedw_old <= audio_wrusedw[7];
      if(!audio_wrusedw[7] && audio_wrusedw_old)begin//1->0
        audio_irq_req <= 1;
      end
      
      if(audio_irq_ack)begin
        audio_irq_req <= 0;
      end

`endif
    end
  end
  
  reg [7:0] audio_data_out;
  always@(*) begin
    case(clk_audio[1:0])
    0:audio_data_out<=audio_q[ 7: 0];
    1:audio_data_out<=audio_q[15: 8];
    2:audio_data_out<=audio_q[23:16];
    3:audio_data_out<=audio_q[31:24];
    endcase
  end
  
  wire [31:0] audio_q;
  wire  audio_rdempty;
  wire [7:0] audio_wrusedw;

  `ifdef AUDIO_FIFO
  dcfifo	audio_fifo (
    .rdclk (clk_audio[3]),
    .rdreq (audio_ena),
    .wrclk (clk_50M),
    .wrreq (audio_wrreq),
    .data (avm_m0_writedata),
    .q (audio_q),
    .rdempty (audio_rdempty),
    .wrusedw (audio_wrusedw),
    .wrfull (),
    .aclr (),
    .rdfull (),
    .rdusedw (),
    .wrempty ());
  defparam
    audio_fifo.intended_device_family = "Cyclone IV E",
    audio_fifo.lpm_numwords = 256,
    audio_fifo.lpm_showahead = "OFF",
    audio_fifo.lpm_type = "dcfifo",
    audio_fifo.lpm_width = 32,
    audio_fifo.lpm_widthu = 8,
    audio_fifo.overflow_checking = "ON",
    audio_fifo.rdsync_delaypipe = 4,
    audio_fifo.underflow_checking = "ON",
    audio_fifo.use_eab = "ON",
    audio_fifo.wrsync_delaypipe = 4;
  `endif
  
  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire ds1302_cs = deviceid == 10;//0x5400_0000 avm_m0_address[31:16] == 16'h0209;
  reg       ds1302_device_ack_reg;
  reg [1:0] ds1302_status;
  reg       ds1302_device_req;
  reg       ds1302_device_ack_buff;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      ds1302_device_ack_reg <= 0;
      ds1302_status <= 0;
      ds1302_device_req <= 0;
      ds1302_device_ack_buff <= 0;
    end else begin
      ds1302_device_ack_buff <= ds1302_device_ack;
      ds1302_device_ack_reg <= 0;
      case(ds1302_status)
      STATUS_INIT: begin
        if(ds1302_cs)begin
          if(device_req && !ds1302_device_ack_reg)begin
            ds1302_device_req <= 1;
            ds1302_status <= STATUS_WAIT;
          end
        end
      end
`ifdef isALTERA
      STATUS_WAIT: begin
        if(ds1302_device_ack_buff)begin
          ds1302_device_req <= 0;
          ds1302_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!ds1302_device_ack_buff)begin
          ds1302_device_ack_reg <= 1;
          ds1302_status <= STATUS_INIT;
        end
      end
`else
      STATUS_WAIT: begin
        ds1302_device_ack_reg <= 1;
        ds1302_status <= STATUS_INIT;
      end
`endif
      endcase
    end
  end

  wire [31:0] ds1302_readdata;
  wire [22:0] ds1302_address = device_address[24:2];//1M byte, 256k word
  wire ds1302_device_ack;

`ifdef isISE
//TODO
`else
spi3wire ds1302_inst (
  .clk_50M            (clk_50M),
  .reset_n            (reset_n), //       reset.reset_n
  .avs_s0_address     (ds1302_address ),
  .avs_s0_rw          (avm_m0_rw ),
  .avs_s0_writedata   (avm_m0_writedata ),
  .avs_s0_readdata    (ds1302_readdata ),
  .device_req         (ds1302_device_req ),
  .device_ack         (ds1302_device_ack ),
  .avs_s0_byteenable  (avm_m0_byteenable ),

  .spi_cs             (ds1302_rst),
  .spi_clk            (ds1302_clk),
  .spi_dat            (ds1302_dat)

);
`endif

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire fpu_cs    = deviceid == 11;//0x5600_0000 avm_m0_address[31:16] == 16'h0209;
  wire fpu_device_ack_reg = 1;
  wire [31:0] fpu_readdata = 0;

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire debugger_cs  = deviceid == 12;// 0x5800_0000

  reg debugger_device_ack;
  reg       debugger_device_ack_reg;
  reg [1:0] debugger_status;
  reg       debugger_device_req;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      debugger_device_ack_reg <= 0;
      debugger_status <= 0;
      debugger_device_req <= 0;
    end else begin
      debugger_device_ack_reg <= 0;
      case(debugger_status)
      STATUS_INIT: begin
        if(debugger_cs)begin
          if(device_req && !debugger_device_ack_reg)begin
            debugger_device_req <= 1;
            debugger_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(debugger_device_ack)begin
          debugger_device_req <= 0;
          debugger_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        debugger_device_ack_reg <= 1;
        debugger_status <= STATUS_INIT;
      end
      endcase
    end
  end
  
  //wire [28:0] systemVer = `SYSTEM_VER;
  reg [31:0] debugger_readdata;
  always@ (*) begin
    case(device_address[3:2])
    0: debugger_readdata <= {debug_tx_to_pc_valid,debug_rx_from_pc_valid,debug_flg};//systemVer,
    1: debugger_readdata <= debug_rx_from_pc;
    2: debugger_readdata <= performance_ins_count;
    3: debugger_readdata <= performance_clk_count;
    endcase
  end
  
  always@(posedge clk or negedge reset_n) begin
    if(!reset_n) begin
      debug_tx_to_pc <= 0;
      debug_tx_to_pc_valid <= 0;
      debug_rx_from_pc_read <= 0;
      debugger_device_ack <= 0;
      performance_count_on<=0;
      performance_count_rst<=0;
    end else begin

      performance_count_rst <= 0;
      
      if(debugger_device_req && !debugger_device_ack)begin
        debugger_device_ack <= 1;
        if(avm_m0_rw)begin
          if(device_address[3:2]==0)begin
            debug_tx_to_pc_valid <= 1;
            debug_tx_to_pc <= avm_m0_writedata;
          end
          if(device_address[3:2]==2)begin
            performance_count_rst <= avm_m0_writedata[0];
            performance_count_on <= avm_m0_writedata[0];
          end
        end else begin
          if(device_address[3:2]==1)begin
            if(debug_rx_from_pc_valid)begin
              debug_rx_from_pc_read <= 1;
            end
          end
        end
      end

      if(!debugger_device_req && debugger_device_ack)begin
        debugger_device_ack <= 0;
      end
      
      
      if(debug_tx_to_pc_valid && debug_tx_to_pc_read)begin
        debug_tx_to_pc_valid <= 0;
      end
      
      if(debug_rx_from_pc_read && !debug_rx_from_pc_valid)begin
        debug_rx_from_pc_read <= 0;
      end
      
    end
  end

  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire ch375_cs  = deviceid == 13;// 0x5A00_0000
  reg       ch375_device_ack_reg;
  reg [1:0] ch375_status;
  reg       ch375_device_req;
  reg       ch375_device_ack_buff;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      ch375_device_ack_reg <= 0;
      ch375_status <= 0;
      ch375_device_req <= 0;
      ch375_device_ack_buff <= 0;
    end else begin
      ch375_device_ack_buff <= ch375_device_ack;
      ch375_device_ack_reg <= 0;
      case(ch375_status)
      STATUS_INIT: begin
        if(ch375_cs)begin
          if(device_req && !ch375_device_ack_reg)begin
            ch375_device_req <= 1;
            ch375_status <= STATUS_WAIT;
          end
        end
      end
      STATUS_WAIT: begin
        if(ch375_device_ack_buff)begin
          ch375_device_req <= 0;
          ch375_status <= STATUS_DELAY;
        end
      end
      STATUS_DELAY: begin
        if(!ch375_device_ack_buff)begin
          ch375_device_ack_reg <= 1;
          ch375_status <= STATUS_INIT;
        end
      end
      endcase
    end
  end

  assign ch375_d = ch375_wr ? 8'bzzzzzzzz : ch375_data_out;
  reg [7:0] ch375_data_out;
  wire [7:0] ch375_data_in = ch375_d;     //寄存从SDRAM中读取的数据

  localparam CH375_STATUS_INIT              = 0;
  localparam CH375_STATUS_READ1             = 1;
  localparam CH375_STATUS_READ1A            = 2;

  localparam TIMELIMIT            = 15;//ok

  reg ch375_device_ack;
  reg ch375_device_req_buff;
  reg [31:0] ch375_readdata;
  reg [1:0] ch375_act_status;
  reg [3:0] delay_count;
  reg [1:0] count;
  `ifdef useCH375
  always@(posedge clk_50M or negedge reset_n) begin
    if(!reset_n) begin
      ch375_data_out <= 0;
      ch375_a0 <= 0;
      ch375_cs_out <= 1;
      ch375_rd <= 1;
      ch375_wr <= 1;
      ch375_device_ack <= 0;
      ch375_device_req_buff <= 0;
      ch375_act_status <= CH375_STATUS_INIT;
      delay_count <= 0;
      ch375_readdata <= 0;
      count <= 0;
    end else begin
      ch375_device_req_buff <= ch375_device_req;

      case(ch375_act_status)
      CH375_STATUS_INIT: begin
        count <= 0;
        if(ch375_device_req_buff && !ch375_device_ack)begin
          if(avm_m0_rw)begin
            ch375_device_ack <= 1;
            if(device_address[4:2] == 0)begin
              ch375_data_out <= avm_m0_writedata[7:0];
            end
            if(device_address[4:2] == 1)begin
              ch375_a0 <= avm_m0_writedata[0];
            end
            if(device_address[4:2] == 2)begin
              ch375_cs_out <= avm_m0_writedata[0];
            end
            if(device_address[4:2] == 3)begin
              ch375_rd <= avm_m0_writedata[0];
            end
            if(device_address[4:2] == 4)begin
              ch375_wr <= avm_m0_writedata[0];
            end
            if(device_address[4:2] == 5)begin
              //write 4 byte
            end

          end else begin
            if(device_address[4:2] == 0)begin
              ch375_device_ack <= 1;
              ch375_readdata <= {ch375_int,ch375_data_in};
            end
            if(device_address[4:2] == 1)begin
              //read 4 byte
              ch375_act_status <= CH375_STATUS_READ1;
              delay_count <= 0;
              ch375_rd <= 0;
            end

          end
        end
      end
      CH375_STATUS_READ1: begin
        delay_count <= delay_count + 1'b1;
        if(delay_count==TIMELIMIT)begin
          ch375_act_status <= CH375_STATUS_READ1A;
          delay_count <= 0;
          //ch375_readdata[7:0] <= ch375_data_in;
          ch375_readdata <= {ch375_data_in,ch375_readdata[31:8]};
          ch375_rd <= 1;
        end
      end
      CH375_STATUS_READ1A: begin
        delay_count <= delay_count + 1'b1;
        if(delay_count==TIMELIMIT)begin
          delay_count <= 0;
          ch375_rd <= 0;
          count <= count+1'b1;
          if(count==3)begin
            ch375_device_ack <= 1;
            ch375_act_status <= CH375_STATUS_INIT;
          end else begin
            ch375_act_status <= CH375_STATUS_READ1;
          end
        end
      end
      //写的话先返回，后置状态到init
      
      endcase
      
      
      
      if(!ch375_device_req_buff && ch375_device_ack)begin
        ch375_device_ack <= 0;
      end
    end
  end
  `endif


  //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  wire rndmisc_cs = deviceid == 15;
  reg rndmisc_device_ack_reg;
  //cpu_clk_sel;
  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      rndmisc_device_ack_reg <= 0;
      //cpu_clk_sel <= 1;
    end else begin
      rndmisc_device_ack_reg <= 0;
      if(rndmisc_cs)begin
        if(device_req && !rndmisc_device_ack_reg)begin
          rndmisc_device_ack_reg <= 1;
        end
        
        //if(device_req && avm_m0_rw)begin
        //  cpu_clk_sel <= avm_m0_writedata[0];
        //end
      end
    end
  end

  wire [31:0] rndmisc_readdata = {31'b0,a^b};
  //wire a=0;
  ringOscillator ro_a(
   .enable(reset_n),
   .ro_out(a)
  );
  //wire b=0;
  ringOscillator ro_b(
   .enable(reset_n),
   .ro_out(b)
  );

  
endmodule


module ringOscillator(
  input enable,
  output ro_out
);
//(* DONT_TOUCH = "1"*) 
wire      notgate_in/* synthesis syn_keep=1 */;
//(* DONT_TOUCH = "1"*) 
wire[4:0] notgate_out/* synthesis syn_keep=1 */;

and u1(notgate_in, notgate_out[4], enable);

not u2(notgate_out[0], notgate_in);

not u3(notgate_out[1], notgate_out[0]);

not u4(notgate_out[2], notgate_out[1]);

not u5(notgate_out[3], notgate_out[2]);

not u6(notgate_out[4], notgate_out[3]);

assign ro_out = notgate_out[4];


endmodule

